import json
import random
import tkinter as tk
from tkinter import messagebox, simpledialog
import os

class LotteryGame:
    def __init__(self, root):
        # 设置中文字体支持
        self.font_config = ('SimHei', 12)
        self.title_font = ('SimHei', 16, 'bold')
        self.card_font = ('SimHei', 24)
        
        self.root = root
        self.root.title("卡牌抽奖游戏")
        # 移除固定尺寸，使用最小尺寸
        self.root.minsize(600, 500)
        self.root.configure(bg="#f0f0f0")
        
        # 初始化变量
        self.config_path = "config.json"
        self.prizes = []
        self.card_count = 9
        self.cards = []
        self.is_drawn = False
        self.winning_card = -1
        self.winning_prize = None
        
        # 创建主框架，使用grid布局
        self.main_frame = tk.Frame(self.root, bg="#f0f0f0")
        self.main_frame.pack(fill=tk.BOTH, expand=True, padx=20, pady=20)
        
        # 为每一行和每一列设置权重，使它们能够扩展
        self.main_frame.grid_rowconfigure(0, weight=1)
        self.main_frame.grid_rowconfigure(1, weight=1)
        self.main_frame.grid_rowconfigure(2, weight=3)
        self.main_frame.grid_rowconfigure(3, weight=1)
        self.main_frame.grid_rowconfigure(4, weight=1)
        self.main_frame.grid_columnconfigure(0, weight=1)
        
        # 加载配置
        self.load_config()
        
        # 创建界面
        self.create_widgets()
        
        # 绑定窗口大小变化事件
        self.root.bind('<Configure>', self.on_window_resize)
        
    def load_config(self):
        """从配置文件加载奖品信息"""
        try:
            with open(self.config_path, 'r', encoding='utf-8') as f:
                config = json.load(f)
                self.prizes = config.get("prizes", [])
                self.card_count = config.get("card_count", 9)
                
            # 验证概率总和是否为1
            total_prob = sum(prize["probability"] for prize in self.prizes)
            if abs(total_prob - 1.0) > 0.001:
                messagebox.showwarning("配置警告", "奖品概率总和不为1，请检查配置文件！")
                
        except Exception as e:
            messagebox.showerror("配置错误", f"无法加载配置文件：{str(e)}")
            # 使用默认配置
            self.prizes = [
                {"name": "28.8", "description": "28.8", "probability": 0.001, "image": "🥇"},
                {"name": "8.8", "description": "8.8", "probability": 0.1, "image": "🥈"},
                {"name": "1.8", "description": "1.8", "probability": 0.2, "image": "🥉"},
                {"name": "谢谢参与", "description": "再接再厉", "probability": 0.699, "image": "🎫"}
            ]
            self.card_count = 9
    
    def create_widgets(self):
        """创建游戏界面组件"""
        # 标题
        title_frame = tk.Frame(self.main_frame, bg="#f0f0f0")
        title_frame.grid(row=0, column=0, sticky="nsew", pady=(0, 10))
        title_frame.grid_columnconfigure(0, weight=1)
        
        title_label = tk.Label(title_frame, text="卡牌抽奖游戏", font=self.title_font, bg="#f0f0f0")
        title_label.pack(pady=10)
        
        # 配置按钮
        config_btn = tk.Button(title_frame, text="配置奖品", font=self.font_config,
                              command=self.open_config_dialog, bg="#4CAF50", fg="white", padx=10, pady=5)
        config_btn.pack(pady=5)
        
        # 卡牌区域
        self.card_frame = tk.Frame(self.main_frame, bg="#f0f0f0")
        self.card_frame.grid(row=2, column=0, sticky="nsew", pady=(10, 10))
        
        # 设置卡牌区域的行和列权重
        for i in range(3):  # 3行
            self.card_frame.grid_rowconfigure(i, weight=1, uniform="card")
        for i in range(3):  # 3列
            self.card_frame.grid_columnconfigure(i, weight=1, uniform="card")
        
        # 创建卡牌
        self.create_cards()
        
        # 结果显示
        self.result_label = tk.Label(self.main_frame, text="点击任意卡牌开始抽奖！", font=self.font_config,
                                    bg="#f0f0f0", wraplength=600)
        self.result_label.grid(row=3, column=0, sticky="nsew", pady=(10, 10))
        
        # 重置按钮
        self.reset_frame = tk.Frame(self.main_frame, bg="#f0f0f0")
        self.reset_frame.grid(row=4, column=0, sticky="nsew", pady=(10, 0))
        self.reset_frame.grid_columnconfigure(0, weight=1)
        
        self.reset_btn = tk.Button(self.reset_frame, text="重新开始", font=self.font_config,
                                  command=self.reset_game, state=tk.DISABLED, bg="#2196F3", fg="white", padx=10, pady=5)
        self.reset_btn.pack(pady=5)
    
    def create_cards(self):
        """创建所有卡牌按钮"""
        # 清空现有卡牌
        for card in self.cards:
            card.destroy()
        self.cards = []
        
        # 创建新卡牌
        for i in range(self.card_count):
            card_btn = tk.Button(self.card_frame, text="?", font=self.card_font,
                                bg="#FFC107", fg="#333333",
                                command=lambda idx=i: self.draw_card(idx))
            # 使用grid布局，sticky参数让按钮填充整个格子
            card_btn.grid(row=i//3, column=i%3, padx=10, pady=10, sticky="nsew")
            self.cards.append(card_btn)
    
    def draw_card(self, card_index):
        """处理卡牌点击事件，执行抽奖"""
        if self.is_drawn:
            messagebox.showinfo("提示", "一次游戏只能抽一次奖，请点击重新开始按钮！")
            return
        
        # 根据概率为所有卡牌分配奖品
        self.assign_prizes_to_cards()
        
        # 用户点击的卡牌作为中奖卡牌
        self.winning_card = card_index
        self.winning_prize = self.card_prizes[card_index]
        
        # 更新所有卡牌显示
        for i, card in enumerate(self.cards):
            prize = self.card_prizes[i]
            # 根据奖品类型设置不同的背景色
            if i == self.winning_card:
                # 突出显示用户点击的卡牌
                card.config(text=prize["image"], bg="#FFD700", fg="#333333")
            else:
                # 根据奖品名称设置不同的背景色
                if prize["name"] == "一等奖" or prize["name"] == "28.8":
                    bg_color = "#FFA07A"  # 浅鲑鱼色
                elif prize["name"] == "二等奖" or prize["name"] == "8.8":
                    bg_color = "#98FB98"  # 淡绿色
                elif prize["name"] == "三等奖" or prize["name"] == "1.8":
                    bg_color = "#87CEEB"  # 天空蓝
                else:
                    bg_color = "#D3D3D3"  # 浅灰色
                card.config(text=prize["image"], bg=bg_color, fg="#333333")
            # 禁用所有卡牌
            card.config(state=tk.DISABLED)
        
        # 更新结果显示
        result_text = f"恭喜您抽到了【{self.winning_prize['name']}】！\n{self.winning_prize['description']}"
        self.result_label.config(text=result_text)
        
        # 标记已抽奖
        self.is_drawn = True
        self.reset_btn.config(state=tk.NORMAL)
    
    def assign_prizes_to_cards(self):
        """根据概率为所有卡牌分配奖品，确保所有奖品类型都至少出现一次"""
        self.card_prizes = []
        
        # 首先确保每种奖品至少出现一次
        all_prizes = []
        # 先添加所有奖品各一次
        for prize in self.prizes:
            all_prizes.append(prize)
        
        # 计算剩余卡牌数量
        remaining_cards = self.card_count - len(self.prizes)
        
        if remaining_cards > 0:
            # 根据各奖品的概率，为剩余卡牌分配奖品
            # 计算概率总和
            total_prob = sum(prize["probability"] for prize in self.prizes)
            
            # 计算每种奖品应该额外出现的次数
            additional_counts = []
            for prize in self.prizes:
                # 基于概率分配剩余卡牌
                count = int(round((prize["probability"] / total_prob) * remaining_cards))
                additional_counts.append((prize, count))
            
            # 确保总卡牌数正确
            total_additional = sum(count for _, count in additional_counts)
            diff = remaining_cards - total_additional
            
            # 调整差异
            if diff > 0:
                # 按概率比例分配剩余卡牌
                probs = [prize["probability"] for prize, _ in additional_counts]
                for _ in range(diff):
                    # 归一化概率
                    total = sum(probs)
                    if total == 0:  # 防止除零错误
                        break
                    normalized_probs = [p/total for p in probs]
                    # 随机选择一个奖品
                    rand = random.random()
                    cumulative = 0
                    for i, prob in enumerate(normalized_probs):
                        cumulative += prob
                        if rand <= cumulative:
                            additional_counts[i] = (additional_counts[i][0], additional_counts[i][1] + 1)
                            break
            elif diff < 0:
                # 需要减少一些卡牌
                # 随机移除一些卡牌，优先移除概率较低的奖品
                # 创建要移除的索引列表
                to_remove = []
                for i, (_, count) in enumerate(additional_counts):
                    if count > 0:
                        to_remove.extend([i] * count)
                
                # 随机移除diff个元素
                random.shuffle(to_remove)
                to_remove = to_remove[:-diff]
                
                # 重新计算additional_counts
                new_additional_counts = [(prize, 0) for prize, _ in additional_counts]
                for idx in to_remove:
                    new_additional_counts[idx] = (new_additional_counts[idx][0], new_additional_counts[idx][1] + 1)
                additional_counts = new_additional_counts
            
            # 添加额外的奖品
            for prize, count in additional_counts:
                all_prizes.extend([prize] * count)
        
        # 确保有9张卡牌
        while len(all_prizes) < self.card_count:
            # 如果奖品不足，添加默认奖品
            default_prize = next((p for p in self.prizes if p["name"] == "谢谢参与"), None)
            if default_prize:
                all_prizes.append(default_prize)
            else:
                all_prizes.append({"name": "谢谢参与", "description": "再接再厉", "image": "🎫"})
        
        # 打乱奖品顺序
        random.shuffle(all_prizes)
        
        self.card_prizes = all_prizes[:self.card_count]  # 确保只有9张卡牌
    
    def reset_game(self):
        """重置游戏"""
        self.is_drawn = False
        self.winning_card = -1
        self.winning_prize = None
        
        # 重置卡牌
        for card in self.cards:
            card.config(text="?", bg="#FFC107", fg="#333333", state=tk.NORMAL)
        
        # 重置结果显示
        self.result_label.config(text="点击任意卡牌开始抽奖！")
        self.reset_btn.config(state=tk.DISABLED)
    
    def open_config_dialog(self):
        """打开配置对话框"""
        # 询问是否加载自定义配置文件
        config_file = simpledialog.askstring("配置", "请输入配置文件路径（默认：config.json）:",
                                            initialvalue=self.config_path, parent=self.root)
        
        if config_file:
            # 检查文件是否存在
            if os.path.exists(config_file):
                self.config_path = config_file
                # 重新加载配置
                self.load_config()
                # 重新创建卡牌
                self.create_cards()
                # 重置游戏
                self.reset_game()
                messagebox.showinfo("配置成功", f"已成功加载配置文件：{config_file}")
            else:
                messagebox.showerror("文件不存在", f"配置文件不存在：{config_file}")
    
    def on_window_resize(self, event):
        """窗口大小变化事件处理"""
        # 这里可以根据窗口大小调整字体大小或其他UI元素
        # 为了简单起见，我们不在这里做太多改变，因为grid布局已经能够很好地处理自适应
        pass

if __name__ == "__main__":
    root = tk.Tk()
    # 设置tkinter支持中文
    root.option_add("*Font", ('SimHei', 10))
    game = LotteryGame(root)
    root.mainloop()